
package com.wwy.monitor.executor;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import com.wwy.monitor.model.enumeration.ComparatorTypeEnum;
import com.wwy.monitor.model.tddl.vo.MonitorTaskVo;
import com.wwy.monitor.util.HttpClientUtils;
import com.wwy.monitor.util.OkHttpUtil;
import com.autonavi.acis.common.utils.IdentifierThreadFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class MonitorExecutor {
    private static ExecutorService executor = new ThreadPoolExecutor(10, 50,
            30, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(5000),
            new IdentifierThreadFactory("monitorExecutor"),
            new RejectedHandler());
    private static Logger logger = LoggerFactory.getLogger(MonitorExecutor.class);

    private static class RejectedHandler implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            if (executor != null && !executor.isShutdown()) {
                r.run();
            }
        }
    }

    static {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            if (executor != null && !executor.isShutdown()) {
                logger.info("colse MonitorExecutor executor");
                executor.shutdown();
            }
        }));
    }

    public static List<Map<String, Object>> getResultByMonitorTask(MonitorTaskVo taskVo) {
//åå»ºä¸ä¸ªçº¿ç¨æ± 
        List<Map<String, Object>> list = Lists.newArrayList();
        if (taskVo.getIpList() != null && taskVo.getIpList().size() > 0) {
            List<Future> futures = Lists.newArrayList();
            for (String ip : taskVo.getIpList()) {
                Callable callable = new MonitorCallable(ip, taskVo);
//æ§è¡ä»»å¡å¹¶è·åFutureå¯¹è±¡
                Future future = executor.submit(callable);
//ä»Futureå¯¹è±¡ä¸è·åä»»å¡çè¿åå¼ï¼å¹¶è¾åºå°æ§å¶å°
                futures.add(future);
            }
            if (futures.size() > 0) {
                for (Future f : futures) {
                    try {
                        list.add((Map<String, Object>) f.get());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                }
            }
            futures.clear();
        }
//å³é­çº¿ç¨æ± 
//executor.shutdown();
        return list;
    }

    public static class MonitorCallable implements Callable<Object> {
        private String ip;
        private MonitorTaskVo taskVo;
        Map<String, Object> resultMap = Maps.newConcurrentMap();

        /**
         * @param ip     æºå¨ip
         * @param taskVo è¯·æ±参数
         */
        public MonitorCallable(String ip, MonitorTaskVo taskVo) {
            this.ip = ip;
            this.taskVo = taskVo;
        }

        @Override
        public Object call() throws Exception {
            String response = "false";
            Integer result = 0;
            boolean isDomain = false;
            if (taskVo.getMonitorType() == 1 && StringUtils.isNotEmpty(taskVo.getDomainUrl())) {
                isDomain = true;
            }
            for (int i = 0; i < 3; i++) {
                try {
                    response = OkHttpUtil.submitForString(taskVo.getProtocol() + ip, taskVo.getPort(), taskVo.getUrl(), taskVo.getRequestMethod(), taskVo.getRequestHeader(), taskVo.getParam(), isDomain, taskVo.getContentType());
                    if (StringUtils.isNotEmpty(response)) {
                        if (StringUtils.isNotEmpty(taskVo.getExceptResult())) {
//éè¦æ¯è¾ æ¯å¦ä¸ææå¼ä¸è´ ä¸ä¸è´ä¸èµå¼
                            switch (taskVo.getComparator()) {
                                case 1:
                                    if (Integer.valueOf(response) > Integer.valueOf(taskVo.getExceptResult())) {
                                        result = 1;
                                    }
                                    break;
                                case 2:
                                    if (Integer.valueOf(response) >= Integer.valueOf(taskVo.getExceptResult())) {
                                        result = 1;
                                    }
                                    break;
                                case 3:
                                    if ((response).equals(taskVo.getExceptResult())) {
                                        result = 1;
                                    }
                                    break;
                                case 4:
                                    if (Integer.valueOf(response) < Integer.valueOf(taskVo.getExceptResult())) {
                                        result = 1;
                                    }
                                    break;
                                case 5:
                                    if (Integer.valueOf(response) <= Integer.valueOf(taskVo.getExceptResult())) {
                                        result = 1;
                                    }
                                    break;
                                default:
                                    break;
                            }
                        } else {
                            result = 1;
                        }
                        break;
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            if (response == null) {
                response = "null";
            }
            resultMap.put("ip", ip);
            resultMap.put("response", response);
            resultMap.put("result", result);
            return resultMap;
        }
    }
}